/* -*-C-*-
 ##############################################################################
 #
 # File:        trice/src/testreg.c
 # RCS:         "@(#)$Revision: 1.19 $ $Date: 94/03/21 16:53:23 $"
 # Description: User routine for doing self test of E1430 module register access
 # Author:      Doug Passey
 # Created:     
 # Language:    C
 # Package:     E1430
 # Status:      "@(#)$State: Exp $"
 #
 # (C) Copyright 1992, Hewlett-Packard Company, all rights reserved.
 #
 ##############################################################################
 #
 # Please add additional comments here
 #
 # Revisions:
 #
 ##############################################################################
*/

#    include <stdio.h>
#    include <math.h>

#include "trice.h"
#include "err1430.h"

#ifndef lint
const char i1430_testreg_fileId[] = "$Header: testreg.c,v 1.19 94/03/21 16:53:23 chriss Exp $";
#endif


/*****************************************************************************
 * 
 * This function test the decoding of the logical address, address modifier,
 * and data width control lines.  It should be run  after setting the 
 * address switches to 0 (all zeros) and again after setting the logical
 * address switches to 255 (all ones).
 *
 * Returns negative error number if error, otherwise returns 0.
 *
 ****************************************************************************/
SHORTSIZ16 e1430_test_logical_address(SHORTSIZ16 la)
{
  SHORTSIZ16 error;
  volatile SHORTSIZ16 reg;
  char buf1[80], buf2[80];

  (void)sprintf(buf1, "%d", (LONGSIZ32)la);

  for(e1430_i=0; e1430_i<256; e1430_i++) {	/* for all logical addresses */
    E1430_TRY

      e1430_addr = e1430_get_register_address((SHORTSIZ16)e1430_i, 	
					E1430_VXI_DEVICE_TYPE_REG);
      reg = iwpeek((USHORTSIZ16 *)e1430_addr);
      E1430_CHECK_BERR
      
      /* responded to incorrect la */
      if(((SHORTSIZ16)e1430_i != la) && (reg == TRICE_DEVICE_TYPE)) {
        e1430_addr = e1430_get_register_address((SHORTSIZ16)e1430_i, 
							E1430_VXI_ID_REG);
        reg = iwpeek((USHORTSIZ16 *)e1430_addr);
        E1430_CHECK_BERR
	if(reg == (SHORTSIZ16)0xFFFF) {  /* if HP card */
	  (void)sprintf(buf2, "%d", (LONGSIZ32)e1430_i);
	  error = i1430_Error(ERR1430_LA_DECODE, buf1, buf2);
	  if(error) return(error);
   	}
      }
    E1430_RECOVER {
      if((SHORTSIZ16)e1430_i == la) {	/* correct module didn't respond */
	error = i1430_Error(ERR1430_LA_TIMEOUT, buf1, NULL);
	if(error) return(error);
      }
    }	/* E1430_RECOVER */

  }

  e1430_addr = e1430_get_register_address(la, E1430_VXI_DEVICE_TYPE_REG);

#ifndef INTEL_PROC
  {
    char ch;
    /* test A16, D8 request */
  E1430_TRY 

      ch = *((char *)e1430_addr);
      E1430_CHECK_BERR
      e1430_addr = (SHORTSIZ16 *)((char *)e1430_addr + 1);
      ch = *((char *)e1430_addr);
      E1430_CHECK_BERR
    E1430_RECOVER {
      return(i1430_Error(ERR1430_D8_TIMEOUT, buf1, NULL));
    }
  }
#endif

  return (0);




}


/*****************************************************************************
 *
 * Print out read error message.
 *
 ****************************************************************************/
static SHORTSIZ16 print_read_error(SHORTSIZ16 reg, SHORTSIZ16 la, 
					SHORTSIZ16 expected, SHORTSIZ16 got)
{
  char buf1[80];
  char buf2[80];

  (void)sprintf(buf1, "offset 0x%X, la = %d", (LONGSIZ32)reg, (LONGSIZ32)la);
  (void)sprintf(buf2, "\n	Expected 0x%X,        Read 0x%X", 
					(LONGSIZ32)expected, (LONGSIZ32)got);
  return(i1430_Error(ERR1430_ILLEGAL_RESPONSE_REG, buf1, buf2));
}


/*****************************************************************************
 *
 * This function tests whether the read/write addresses are correctly 
 * decoded and verifies the contents of most registers.
 *
 ****************************************************************************/
SHORTSIZ16 e1430_test_register_access(SHORTSIZ16 la)
{
  volatile SHORTSIZ16 reg;
  SHORTSIZ16 value, error;
  char buf1[80];
  char buf2[80];

  (void)sprintf(buf1, "%d", (LONGSIZ32)la);
  
  for(e1430_i=0; e1430_i <= E1430_LO_TRANSFER_REG; e1430_i+=2) {  /* test all writable registers */
    e1430_addr = e1430_get_register_address(la, (SHORTSIZ16)e1430_i);
    E1430_TRY

      iwpoke((USHORTSIZ16 *)e1430_addr, 0);
      E1430_CHECK_BERR
      switch(e1430_i) {	/* check for response to illegal write address */
	case 0:
	case 2:
	case 14:
	case 16:
	case 18:
	case 32:
	case 34:
	  (void)sprintf(buf2, "0x%X", (LONGSIZ32)e1430_i);
	  error = i1430_Error(ERR1430_ILLEGAL_WRITE_RESPONSE, buf2, buf1);
  	  if(error) return(error);
	  break;
      }

    E1430_RECOVER {
      switch(e1430_i) {
        case E1430_VXI_CONTROL_REG:
        case E1430_ANALOG_SETUP_REG:
        case E1430_INPUT_OFFSET_REG:
        case E1430_MEAS_CONTROL_REG:
        case E1430_DATA_FORMAT_REG:
        case E1430_IRQ_CONFIG_0_REG:
        case E1430_IRQ_CONFIG_1_REG:
        case E1430_HP_PORT_CONTROL_REG:
        case E1430_TRIGGER_SETUP_REG:
        case E1430_TRIGGER_BLOCKSIZE_REG:
        case E1430_TRIGGER_OFFSET_LO_REG:
        case E1430_TIMING_SETUP_REG:
        case E1430_ADC_CONTROL_REG:
        case E1430_TRIGGER_PASSOUT_REG:
        case E1430_DECIMATION_RESET_REG:
        case E1430_DECIMATION_CAPTURE_REG:
        case E1430_ZOOM_PHASE_0_REG:
        case E1430_ZOOM_PHASE_1_REG:
        case E1430_ZOOM_INTERP_0_REG:
        case E1430_ZOOM_INTERP_1_REG:
        case E1430_ZOOM_INTERP_2_REG:
        case E1430_ZOOM_INTERP_3_REG:
        case E1430_ZOOM_CONTROL_REG:
        case E1430_LO_TRANSFER_REG:
	  (void)sprintf(buf2, "0x%X", (LONGSIZ32)e1430_i);
	  error = i1430_Error(ERR1430_WRITE_TIMEOUT, buf2, buf1);
  	  if(error) return(error);
	  break;
      }	/* switch */
    }	/* E1430_RECOVER */
  }	/* for */


  for(e1430_i=0; e1430_i <= E1430_LO_TRANSFER_REG; e1430_i+=2) {  /* test all readable registers */
    e1430_addr = e1430_get_register_address(la, (SHORTSIZ16)e1430_i);
    E1430_TRY

      reg = iwpeek((USHORTSIZ16 *)e1430_addr);
      E1430_CHECK_BERR
      switch(e1430_i) {
        case E1430_VXI_ID_REG:
	  if(reg != (SHORTSIZ16)0xFFFF) {
            return(print_read_error((SHORTSIZ16)e1430_i, la, 0xFFFF, reg));
	  }
	  break;
  
        case E1430_VXI_DEVICE_TYPE_REG:
	  if(reg != (SHORTSIZ16)0x1C6) {
            return(print_read_error((SHORTSIZ16)e1430_i, la, 0x1C6, reg));
	  }
	  break;
  
        case E1430_VXI_STATUS_REG:
	  e1430_cur_status = reg;
	  reg &= 0x0C; 		/* only look at PASSED and READY */
	  value = 0xC;
	  if(reg != value) {
            return(print_read_error((SHORTSIZ16)e1430_i, la, value, reg));
	  }
	  break;
  
        case E1430_HP_PORT_CONTROL_REG:
	  reg &= 0xFCDC;			/* only send port, rec port */
	  value = 0xFC40;
	  if(reg != value) {
            return(print_read_error((SHORTSIZ16)e1430_i, la, value, reg));
	  }
	  break;
  
        case E1430_HP_COMMON_REG:
	  if(reg != 0) {
            return(print_read_error((SHORTSIZ16)e1430_i, la, 0, reg));
	  }
	  break;
  
        case E1430_HP_DESCRIPTION_REG:
	  if(reg != (SHORTSIZ16)0xFB42) {
            return(print_read_error((SHORTSIZ16)e1430_i, la, 0xFE42, reg));
	  }
	  break;
  
        case E1430_HP_SUBCLASS_REG:
	  if(reg != (SHORTSIZ16)0x7FFF) {
            return(print_read_error((SHORTSIZ16)e1430_i, la, 0x7FFF, reg));
	  }
	  break;
  
        default:
          if((SHORTSIZ16)e1430_i < E1430_DECIMATION_CNTLAT_0_REG && 
				(SHORTSIZ16)e1430_i != E1430_HP_SEND_DATA_REG) {
	    (void)sprintf(buf2, "0x%X", (LONGSIZ32)e1430_i);
	    error = i1430_Error(ERR1430_ILLEGAL_READ_RESPONSE, buf2, buf1);
  	    if(error) return(error);
          }
      }	/* switch(e1430_i) */

    E1430_RECOVER {
      if((SHORTSIZ16)e1430_i >= E1430_DECIMATION_CNTLAT_0_REG) {
	(void)sprintf(buf2, "0x%X",(LONGSIZ32) e1430_i);
	error = i1430_Error(ERR1430_NO_RESPONSE_DSP, buf2, buf1);
  	if(error) return(error);
      }
										
    }	/* E1430_RECOVER */ 
  }	/* for all addresses */


  /* test all legal combinations on the E1430_HP_PORT_CONTROL_REG */
  e1430_addr = e1430_get_register_address(la, E1430_HP_PORT_CONTROL_REG);

  for(e1430_i=0; e1430_i < 32; e1430_i++) {
    value = (SHORTSIZ16)(64 + (e1430_i%4) + ((e1430_i & 4) << 3) + ((e1430_i & 0x18) << 5));
    E1430_TRY

      iwpoke((USHORTSIZ16 *)e1430_addr, value);
      E1430_CHECK_BERR
      reg = iwpeek((USHORTSIZ16 *)e1430_addr);
      E1430_CHECK_BERR
      reg &= 0x3FF;		/* mask off upper bits */
      if(reg != value) {
	(void)sprintf(buf2, "	Wrote: 0x%X		Read: 0x%X\n", 
					(LONGSIZ32)value, (LONGSIZ32)reg);
	error = i1430_Error(ERR1430_PORT_CONTROL_RW, buf1, buf2);
  	if(error) return(error);
      }
    E1430_RECOVER {
      error = i1430_Error(ERR1430_PORT_CONTROL_BAD, buf1, NULL);
      if(error) return(error);
    }
  }


  /* check soft reset */
  /* Removed this test for Command module drivers -- it kills
   * the command module for some reason.  Chris S  A.03.00
   */

  e1430_addr = e1430_get_register_address(la, E1430_VXI_CONTROL_REG);

  E1430_TRY 

    iwpoke((USHORTSIZ16 *)e1430_addr,  1);
    E1430_CHECK_BERR
    e1430_addr = e1430_get_register_address(la, E1430_DECIMATION_CNTLAT_0_REG);
    /* expect illegal attempt to read reg while in reset */
    reg = iwpeek((USHORTSIZ16 *)e1430_addr);	
    E1430_CHECK_BERR
    error = i1430_Error(ERR1430_SOFT_RESET_FAIL, buf1, NULL);
    if(error) return(error);

  E1430_RECOVER {
    ;		/* nothing, since error is expected */
  }

  e1430_addr = e1430_get_register_address(la, E1430_VXI_CONTROL_REG);
  iwpoke( (USHORTSIZ16 *)e1430_addr, 0);	/* remove reset */

  return (0);
}

